package com.lagou.ipersistence.executor;

import com.lagou.ipersistence.mapping.BoundSql;
import com.lagou.ipersistence.mapping.MappedStatement;
import com.lagou.ipersistence.session.Configuration;
import com.lagou.ipersistence.session.ResultHandler;
import com.lagou.ipersistence.session.RowBounds;
import com.lagou.ipersistence.transaction.Transaction;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

/**
 * @author Yan Jiahong
 * Created on 2020/11/22
 */
public abstract class BaseExecutor implements Executor {
    protected Transaction transaction;
    protected Configuration configuration;
    protected boolean closed;
    protected Executor wrapper;
    
    public BaseExecutor(Configuration configuration, Transaction transaction) {
        this.configuration = configuration;
        this.transaction = transaction;
        this.closed = false;
        this.wrapper = this;
    }
    
    @Override
    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler<?> resultHandler) throws SQLException {
        BoundSql boundSql = ms.getBoundSql(parameter);
        return query(ms, parameter, rowBounds, resultHandler, boundSql);
    }
    
    @Override
    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler<?> resultHandler, BoundSql boundSql) throws SQLException {
        if (closed) {
            throw new ExecutorException("执行器已经关闭!");
        }
        return queryFromDatabase(ms, parameter, rowBounds, resultHandler, boundSql);
    }
    
    private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler<?> resultHandler, BoundSql boundSql) throws SQLException {
        return doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    }
    
    protected void closeStatement(Statement statement) {
        if (statement != null) {
            try {
                if (!statement.isClosed()) {
                    statement.close();
                }
            } catch (Exception e) {
                // do nothing
            }
        }
    }

    protected Connection getConnection() throws SQLException {
        return transaction.getConnection();
    }
    
    @Override
    public int update(MappedStatement ms, Object arg) throws SQLException{
        return doUpdate(ms,arg);
    }
    
    @Override
    public void commit() throws SQLException{
        transaction.commit();
    }
    
    @Override
    public void close() throws SQLException {
        transaction.close();
    }

    protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler<?> resultHandler, BoundSql boundSql) throws SQLException;

    protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;
}
